package com.cruise.game.common.config;

import com.aliyun.oss.ClientBuilderConfiguration;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.comm.SignVersion;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import java.util.Map;

/**
 * 阿里云OSS配置
 *
 * @author cruise
 * @date 2025-02-28
 */
@Data
@Slf4j
@Configuration
@ConfigurationProperties(prefix = "aliyun.oss")
public class OssConfig {

    /**
     * 标准端点地址
     */
    private String endpoint;

    /**
     * 接入点端点地址
     */
    private String accessPointEndpoint;

    /**
     * 是否使用接入点
     */
    private boolean useAccessPoint;

    /**
     * 访问密钥ID
     */
    private String accessKeyId;

    /**
     * 访问密钥密码
     */
    private String accessKeySecret;

    /**
     * 存储桶名称
     */
    private String bucketName;

    /**
     * 基础URL
     */
    private String baseUrl;

    /**
     * 存储配置
     */
    private Map<String, String> storage;

    /**
     * 客户端配置
     */
    private Map<String, String> client;

    /**
     * 实际使用的端点
     */
    private String actualEndpoint;

    @PostConstruct
    public void init() {
        // 确定实际使用的endpoint
        if (useAccessPoint && StringUtils.isNotBlank(accessPointEndpoint)) {
            actualEndpoint = accessPointEndpoint;
            log.info("OssConfig初始化 - 使用接入点endpoint: {}, bucket: {}", actualEndpoint, bucketName);
        } else {
            actualEndpoint = endpoint;
            log.info("OssConfig初始化 - 使用标准endpoint: {}, bucket: {}", actualEndpoint, bucketName);
        }

        // 打印存储目录配置
        if (storage != null) {
            log.info("OSS存储目录配置: {}", storage);
        }

        // 打印客户端配置
        if (client != null) {
            log.info("OSS客户端配置: {}", client);
        }
    }

    /**
     * 创建OSS客户端
     */
    @Bean
    public OSS ossClient() {
        // 创建ClientConfiguration
        ClientBuilderConfiguration clientConfig = new ClientBuilderConfiguration();

        // 如果有客户端配置，应用它们
        if (client != null) {
            // 设置签名版本
            if (client.containsKey("sign-version") && "V4".equalsIgnoreCase(client.get("sign-version"))) {
                clientConfig.setSignatureVersion(SignVersion.V4);
                log.debug("设置OSS签名版本为: V4");
            }

            // 设置连接超时
            if (client.containsKey("connection-timeout")) {
                try {
                    int timeout = Integer.parseInt(client.get("connection-timeout"));
                    clientConfig.setConnectionTimeout(timeout);
                    log.debug("设置OSS连接超时: {}ms", timeout);
                } catch (NumberFormatException e) {
                    log.warn("解析连接超时配置失败，使用默认值", e);
                }
            }

            // 设置请求超时
            if (client.containsKey("request-timeout")) {
                try {
                    int timeout = Integer.parseInt(client.get("request-timeout"));
                    clientConfig.setSocketTimeout(timeout);
                    log.debug("设置OSS请求超时: {}ms", timeout);
                } catch (NumberFormatException e) {
                    log.warn("解析请求超时配置失败，使用默认值", e);
                }
            }
        }

        // 记录创建客户端时使用的endpoint
        log.debug("创建OSS客户端，endpoint: {}, accessKeyId: {}", actualEndpoint, accessKeyId);

        // 使用标准方式创建客户端
        return new OSSClientBuilder().build(actualEndpoint, accessKeyId, accessKeySecret, clientConfig);
    }

    /**
     * 获取目录配置，如不存在则返回默认值
     * 
     * @param key          配置键
     * @param defaultValue 默认值
     * @return 配置值
     */
    public String getStorageDir(String key, String defaultValue) {
        if (storage != null && storage.containsKey(key)) {
            return storage.get(key);
        }
        return defaultValue;
    }
}